// server.c - Unix本地套接字服务器端实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <errno.h>

#define SOCKET_PATH "/tmp/my_unix_socket"  // 套接字文件路径
#define BACKLOG 5                         // 最大连接队列长度
#define BUFFER_SIZE 1024                  // 缓冲区大小

// 信号处理函数：用于优雅关闭服务器
void signal_handler(int signum) {
    if (signum == SIGINT || signum == SIGTERM) {
        // 删除套接字文件
        unlink(SOCKET_PATH);
        printf("\n服务器已关闭\n");
        exit(EXIT_SUCCESS);
    }
}

int main() {
    int server_fd, client_fd;
    struct sockaddr_un server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE] = {0};
    int bytes_received;

    //1、 注册信号处理函数
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);

    //2、 创建套接字
    server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket创建失败");
        exit(EXIT_FAILURE);
    }

    //3、 清除并设置地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1);

    //4、 删除可能存在的旧套接字文件
    unlink(SOCKET_PATH);

    //5、 绑定地址
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 设置套接字文件权限（可选）
    if (chmod(SOCKET_PATH, 0660) == -1) {
        perror("chmod失败");
        close(server_fd);
        unlink(SOCKET_PATH);
        exit(EXIT_FAILURE);
    }

    // 监听连接
    if (listen(server_fd, BACKLOG) == -1) {
        perror("listen失败");
        close(server_fd);
        unlink(SOCKET_PATH);
        exit(EXIT_FAILURE);
    }

    printf("服务器已启动，等待连接...\n");

    while (1) {
        // 接受客户端连接
        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
        if (client_fd == -1) {
            if (errno == EINTR) {
                continue;  // 处理被信号中断的系统调用
            }
            perror("accept失败");
            continue;
        }

        printf("客户端已连接\n");

        // 循环接收数据
        while ((bytes_received = recv(client_fd, buffer, sizeof(buffer), 0)) > 0) {
            printf("收到消息: %s\n", buffer);

            // 回显数据给客户端
            if (send(client_fd, buffer, bytes_received, 0) == -1) {
                perror("send失败");
                break;
            }
            memset(buffer, 0, sizeof(buffer));
        }

        if (bytes_received == -1) {
            perror("recv失败");
        } else if (bytes_received == 0) {
            printf("客户端已断开连接\n");
        }

        // 关闭客户端连接
        close(client_fd);
    }

    // 关闭服务器套接字（不会执行到这里，由信号处理函数处理）
    close(server_fd);
    unlink(SOCKET_PATH);

    return 0;
}
